package cn.lichenfei.jfx.music.common.utils;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.Console;
import cn.hutool.core.text.csv.CsvData;
import cn.hutool.core.text.csv.CsvReader;
import cn.hutool.core.text.csv.CsvUtil;
import cn.hutool.core.text.csv.CsvWriter;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.StrUtil;
import cn.lichenfei.jfx.music.common.Config;
import cn.lichenfei.jfx.music.common.MusicPlayer;
import cn.lichenfei.jfx.music.common.model.AudioInfo;
import com.alibaba.fastjson.JSON;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author ChenFei
 * @date 2022/5/3
 */
public class AudioDataUtil {

    private static final String[] DEFAULT_MUSIC = {"mp3/music.mp3"};//系统自带音频文件
    private static List<AudioInfo> audioInfoList = new ArrayList<>();
    private static Set<String> pathSet = new HashSet<>();

    /**
     * 初始化本地音频数据
     */
    static {
        try {
            List<AudioInfo> readList = readCsv();
            if (readList.isEmpty()) {
                //初始化内部音频资源
                for (int i = 0; i < DEFAULT_MUSIC.length; i++) {
                    AudioInfo audioInfo = new AudioInfo(DEFAULT_MUSIC[i], true);
                    audioInfoList.add(audioInfo);
                }
            }
            audioInfoList.addAll(readList);
            pathSet = audioInfoList.stream().map(AudioInfo::getPath).collect(Collectors.toSet());
            Console.log("初始化到音频数据size：{}", audioInfoList.size());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取数量
     *
     * @return
     */
    public static int getSize() {
        return audioInfoList.size();
    }

    /**
     * 根据下标获取音频数据
     *
     * @param index
     * @return
     */
    public static AudioInfo getAudio(int index) {
        return audioInfoList.get(index);
    }

    /**
     * 根据下标删除音频数据
     *
     * @param index
     */
    public static void removeAudio(int index) {
        if (index <= MusicPlayer.currentIndex) {
            MusicPlayer.currentIndex = MusicPlayer.currentIndex - 1;
            Config.setLastTimeMusic(MusicPlayer.currentIndex);
        }
        audioInfoList.remove(index);
    }

    /**
     * 分页获取数据
     *
     * @param pageNum
     * @return
     */
    public static List<AudioInfo> page(int pageNum, int pageSize) {
        Console.log("pageNum:{} , pageSize:{} , size:{}", pageNum, pageSize, getSize());
        int offset = pageSize * (pageNum - 1);
        return audioInfoList.stream().skip(offset).limit(pageSize).collect(Collectors.toList());
    }

    /**
     * 获取所有数据
     *
     * @return
     */
    public static List<AudioInfo> getAll() {
        return audioInfoList;
    }

    /**
     * 添加:返回当前，去重
     */
    public static List<AudioInfo> add(List<AudioInfo> addList) {
        Optional.of(addList).ifPresent(list -> {
            List<AudioInfo> infoList = list
                    .stream()
                    .filter(audioInfo -> {
                        if (!pathSet.contains(audioInfo.getPath())) {
                            pathSet.add(audioInfo.getPath());
                            return true;
                        }
                        return false;
                    })
                    .collect(Collectors.toList());
            audioInfoList.addAll(infoList);
        });
        return audioInfoList;
    }

    /**
     * 获取文件夹下的音频文件
     *
     * @param path
     * @return
     * @throws IOException
     */
    public static List<AudioInfo> getAudioList(String path) throws IOException {
        List<AudioInfo> infoList = new ArrayList<>();
        if (StrUtil.isNotBlank(path) && FileUtil.isDirectory(path)) {
            infoList = Files.walk(Paths.get(path))
                    .filter(Files::isRegularFile)
                    .filter(f -> {//过滤非音频文件
                        try {
                            String contentType = Files.probeContentType(f.toAbsolutePath());
                            if (contentType.indexOf("audio") != -1) {
                                return true;
                            }
                            return false;
                        } catch (IOException e) {
                            e.printStackTrace();
                            return false;
                        }
                    })
                    .map(p -> new AudioInfo(p.toUri().getPath(), false))
                    .collect(Collectors.toList());
        }
        return infoList;
    }

    /**
     * 生成csv文件
     *
     * @param infoList
     */
    public static void createCsv(List<AudioInfo> infoList) {
        String path = Config.MUSIC_CSV;
        if (!FileUtil.exist(path) || !FileUtil.isFile(path)) {
            FileUtil.touch(path);
        }
        //指定路径和编码
        CsvWriter writer = CsvUtil.getWriter(path, CharsetUtil.CHARSET_UTF_8);
        //写入
        List<String[]> writerList = infoList
                .stream()
                .map(audioInfo -> new String[]{audioInfo.getName(), audioInfo.getPath(), audioInfo.getInternalResource().toString()})
                .collect(Collectors.toList());
        writer.write(writerList);
        writer.close();
    }

    /**
     * 读取csv文件
     *
     * @return
     */
    public static List<AudioInfo> readCsv() throws IOException {
        List<AudioInfo> infoList = new ArrayList<>();
        if (!FileUtil.exist(Config.MUSIC_CSV)) {
            return infoList;
        }
        final CsvReader reader = CsvUtil.getReader();
        CsvData rows = reader.read(FileUtil.file(Config.MUSIC_CSV), CharsetUtil.CHARSET_UTF_8);
        infoList = rows.getRows()
                .stream()
                .map(row -> new AudioInfo(row.get(0), row.get(1), Boolean.valueOf(row.get(2))))
                .collect(Collectors.toList());
        reader.close();
        Console.log("获取到音频数据：{}", JSON.toJSONString(infoList));
        return infoList;
    }

}
